package com.cheng.tetris.Tetris;

import com.cheng.tetris.Rectangle;

import java.util.ArrayList;
import java.util.List;

public abstract class Tetris
{
    //预判下落位置的方块
    protected Tetris shadow;
    protected List<Rectangle> rectangles;

    protected Rectangle position;//此对象储存块的左上角坐标，所有的块的坐标根据这个计算

    protected int state;//旋转情况

    protected int n;//代表某种块有几种形态

    public Tetris()
    {
        rectangles = new ArrayList<>();
        position = new Rectangle();
        state = 1;
        for (int i = 0; i < 4; i++)
        {
            rectangles.add(new Rectangle());
        }
        resetPosition();
    }

    //根据数值获取俄罗斯方块，每个方块有编号
    public static Tetris getTetris(int i)
    {
        Tetris tetris = null;
        switch (i)
        {
            case 1:
                tetris = new OrangeRicky();
                tetris.shadow = new OrangeRicky();
                break;
            case 2:
                tetris = new Hero();
                tetris.shadow = new Hero();
                break;
            case 3:
                tetris = new BlueRicky();
                tetris.shadow = new BlueRicky();
                break;
            case 4:
                tetris = new Teewee();
                tetris.shadow = new Teewee();
                break;
            case 5:
                tetris = new CleverLandZ();
                tetris.shadow = new CleverLandZ();
                break;
            case 6:
                tetris = new SmashBoy();
                tetris.shadow = new SmashBoy();
                break;
            case 7:
                tetris = new RhodeIslandZ();
                tetris.shadow = new RhodeIslandZ();
                break;
        }
        return tetris;
    }

    public List<Rectangle> getRectangles()
    {
        return rectangles;
    }

    public void setRectangles(List<Rectangle> rectangles)
    {
        this.rectangles = rectangles;
    }

    //判断传入的集合里面是否有块重合
    public boolean isCoincide(List<Rectangle> rectangles)
    {
        synchronized (rectangles)
        {
            for (Rectangle rectangle : rectangles)
            {
                for (Rectangle rectangleLocal : this.rectangles)
                {
                    if (rectangle.getX() == rectangleLocal.getX() && rectangle.getY() == rectangleLocal.getY())
                    {
                        //重合了，返回true
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public void turn(List<Rectangle> rectangles)
    {
        toState((state + 1) > n ? 1 : (state + 1));//变到下一种状态
        if (isCoincide(rectangles))
        {
            //重合了则回退
            toState(state);
            return;
        }
        boolean isOut = false;//是否出下界，出界不转
        for (Rectangle rectangle : this.rectangles)
        {
            isOut = (rectangle.getY() > 20) ? true : isOut;
        }
        //出下界回退
        if (isOut)
        {
            toState(state);
            return;
        }

        //没重合也没出下届就则保存
        state = state + 1 > n ? 1 : state + 1;
        do
        {
            isOut = false;//出界标志，出界了就往里挪一下，再循环判断一遍
            for (Rectangle rectangle : this.rectangles)
            {
                //左边出界往右挪，右边出界往左挪
                if (rectangle.getX() < 1)
                {
                    position.setX(position.getX() + 1);
                    toState(state);
                    isOut = true;
                    if (isCoincide(rectangles))
                    {
                        position.setX(position.getX() + -1);
                        //如果往里挪完了就重合了那退回去
                        state = state - 1 < 1 ? n : state - 1;
                        toState(state);
                    }
                }
                if (rectangle.getX() > 10)
                {
                    position.setX(position.getX() - 1);
                    toState(state);
                    isOut = false;
                    if (isCoincide(rectangles))
                    {
                        position.setX(position.getX() + 1);
                        //如果往里挪完了就重合了那退回去
                        state = state - 1 < 1 ? n : state - 1;
                        toState(state);
                        isOut = false;
                    }
                }
            }
        }
        while (isOut);
    }

    //下移方法
    public boolean moveDown(List<Rectangle> rectangles)
    {
        synchronized (rectangles)
        {

            //比较每一块下面是否有块或者到底，如果有返回false下落失败
            for (Rectangle thisRectangle : this.rectangles)
            {
                //判断是否到底
                if (thisRectangle.getY() > 19)
                {
                    return false;
                }
                for (Rectangle rectangle : rectangles)
                {
                    //判断是否下面有块
                    if (thisRectangle.getX() == rectangle.getX() && thisRectangle.getY() == rectangle.getY() - 1)
                    {
                        return false;
                    }
                }
            }
            //整体下移
            position.setY(position.getY() + 1);
            toState(state);

        }
        return true;
    }

    //直接到底,之后把自己所有的块都返回
    public List<Rectangle> moveBottom(List<Rectangle> rectangles)
    {
        while (moveDown(rectangles))
        {

        }
        return this.rectangles;
    }

    //左移方法
    public void moveLeft(List<Rectangle> rectangles)
    {
        synchronized (rectangles)
        {
            //先左挪一步，看行不行
            position.setX(position.getX() - 1);
            toState(state);

            for (Rectangle thisRectangle : this.rectangles)
            {
                //如果出墙了就给挪回来
                if (thisRectangle.getX() < 1)
                {
                    position.setX(position.getX() + 1);
                    toState(state);
                }
            }
            //如果某一块重合了就挪回来
            if (isCoincide(rectangles))
            {
                position.setX(position.getX() + 1);
                toState(state);
            }
        }
        return;
    }

    //右移方法
    public void moveRight(List<Rectangle> rectangles)
    {
        synchronized (rectangles)
        {

            //先左挪一步，看行不行
            position.setX(position.getX() + 1);
            toState(state);

            for (Rectangle thisRectangle : this.rectangles)
            {
                //如果出墙了就给挪回来
                if (thisRectangle.getX() > 10)
                {
                    position.setX(position.getX() - 1);
                    toState(state);
                }
            }
            //如果某一块重合了就挪回来
            if (isCoincide(rectangles))
            {
                position.setX(position.getX() - 1);
                toState(state);
            }
        }
        return;
    }

    //无条件把本方块的所有信息抄到影子里
    private void copyToShadow()
    {
        shadow.position.setXY(position.getX(), position.getY());
        shadow.state = state;
        shadow.toState(shadow.state);
    }

    public Tetris getShadow(List<Rectangle> rectangles)
    {
        //先把本方块抄到影子里，然后直接让影子落到最底下
        copyToShadow();
        synchronized (rectangles)
        {
            shadow.moveBottom(rectangles);
        }
        return shadow;
    }

    //切换到指定状态
    protected abstract void toState(int state);

    //回到块的出生位置
    public abstract void resetPosition();
    //去示范下一块的位置
    public abstract void toShowNextPosition();


}
